# @Time    : 2019-12-25 09:39
# @Author  : peng
# @File    : sword.py 执行git命令
import logging
import subprocess


def git_clone(git_root, opt_addr):
    ret = execute_cmd(['git', 'clone', git_root], cwd=opt_addr, timeout=300)
    logging.info(ret)


def reset_pull(git_root):
    ret = execute_cmd(['git', 'reset', '--hard', 'HEAD'], cwd=git_root, timeout=30)
    logging.info(ret)
    pull(git_root)


def pull(git_root):
    try:
        ret = execute_cmd(['git', 'pull'], cwd=git_root, timeout=300)
    except Exception as ex:  # retry once
        ret = execute_cmd(['git', 'pull'], cwd=git_root, timeout=300)
    logging.info(ret)


def git_last_log(git_root, timeout=5):
    # git log --pretty=format:"%h -%d %s (%cr) <%an>" --abbrev-commit -1
    ret = execute_cmd(['git', 'log', '--pretty=format:%h -%d %s (%cr) <%an>', '--abbrev-commit', '-1'], cwd=git_root, timeout=timeout)
    return ret


def execute_cmd(args: list, cwd=None, timeout=60, pip=True, ignore=False, strip=True):
    if isinstance(args, str): args = [args, ]
    if cwd and not isinstance(cwd, str):
        cwd = str(cwd)
    logging.info('[CMD] (%s): %s', cwd, ' '.join("'{0}'".format(x) for x in args))
    try:
        with subprocess.Popen(args, stdout=subprocess.PIPE if pip else None, cwd=cwd) as proc:
            try:
                output, unused_err = proc.communicate(timeout=timeout)
            except:
                proc.kill()
                raise
            retcode = proc.poll()
            if retcode:
                raise subprocess.CalledProcessError(retcode, proc.args, output=output)
            ret = output.decode('utf-8', 'ignore') if output else ''
            return ret.strip() if strip else ret
    except subprocess.CalledProcessError as cpe:
        logging.error('EXECUTE_CMD_ERROR <%s,code=%s>: %s', cwd, cpe.returncode, ' '.join(args))
        if ignore:
            return None
        else:
            raise cpe
    except Exception as ex:
        logging.error('EXECUTE_CMD_ERROR <%s>: %s', cwd, ' '.join(str(x) for x in args))
        if ignore:
            return None
        else:
            raise ex
